#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 5e3 + 10;
const int M = 2e5 + 10;

int n, m;

struct Edge
{
    int from, to, next, w;
    bool operator<(const Edge &e)
    {
        return this->w < e.w;
    }
} e[M];

int head[N], idx = 1;

void add_edge(int u, int v, int w)
{
    e[idx].from = u;
    e[idx].to = v;
    e[idx].next = head[u];
    e[idx].w = w;
    head[u] = idx++;
}
void clear_graph()
{
    memset(head, -1, sizeof(head));
    memset(e, 0, sizeof(e));
    idx = 1;
}

int f[M];

int find(int x)
{
    return (f[x] != x) ? (f[x] = find(f[x])) : f[x];
}

void merge(int x, int y)
{
    f[find(x)] = find(y);
}

int mst()
{
    ll res = 0;
    // 先对边按权值排序
    sort(e + 1, e + m + 1);
    // 初始化并查集
    for (int i = 1; i <= m; i++)
        f[i] = i;
    
    int cnt = 0;
    // 从短边开始枚举
    for (int i = 1; i <= m && cnt < n-1; i++)
    {
        int x = e[i].from, y = e[i].to;
        // 如果能连就连
        if (find(x) != find(y))
        {
            merge(x, y);
            res += e[i].w;
            cnt ++;
        }
    }

    return res;
}

int main()
{
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    ios::sync_with_stdio(false), cin.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int x, y, z;
        cin >> x >> y >> z;
        add_edge(x, y, z);
    }

    cout << mst() << endl;
    return 0;
}